#include <iostream>

#include <boost/program_options.hpp>

#ifdef _WIN32
#   include <windows.h>
#endif // _WIN32

#include "../include/FileChangeObserver.h"

enum
{
    TIMER_INTERVAL_MIN = 100,
    UPDATE_FREQ_MIN = 5
};



int main(int argc, char** argv)
{
    namespace prog_opts = boost::program_options;
    namespace filesys = boost::filesystem;

    prog_opts::options_description opts_descr{"Available options"};
    uint32_t timer_interval{};
    uint32_t update_frequency{};

#if 1
    opts_descr.add_options()
        ("help,h", "show help message")

        ("paths,P", prog_opts::value<std::vector<filesys::path>>()
         ->value_name("paths")
         ->multitoken(),
         "paths to directories for monitoring")

        ("timer-interval,T", prog_opts::value<uint32_t>(&timer_interval)
         ->value_name("msec")
         ->default_value(TIMER_INTERVAL_MIN * 10),
         "timer interval (in msec)")

        ("update-freq,U", prog_opts::value<uint32_t>(&update_frequency)
         ->value_name("freq")
         ->default_value(UPDATE_FREQ_MIN * 6),
         "update fequency")
    ;
#endif

    try
    {
        prog_opts::variables_map parsed_options{};
        prog_opts::store(prog_opts::parse_command_line(argc, argv, opts_descr), parsed_options);
        prog_opts::notify(parsed_options);

        if (parsed_options.count("help") || parsed_options.size() < 1)
        {
            std::cout << opts_descr;
            return 0;
        }

        if (!parsed_options.count("paths"))
        {
            std::cerr << "Error: required option --paths (see help)\n";
            return 1;
        }

        if (timer_interval < TIMER_INTERVAL_MIN)
        {
            std::cerr << "Error: timer interval cannot be less than " << TIMER_INTERVAL_MIN << "\n";
            return 1;
        }

        if (update_frequency < UPDATE_FREQ_MIN)
        {
            std::cerr << "Error: update frequency cannot be less than " << TIMER_INTERVAL_MIN << "\n";
            return 1;
        }

        alex::FileChangeObserver file_change_observer {
            parsed_options["paths"].as<std::vector<filesys::path>>(),
                    timer_interval,
                    update_frequency
        };

        file_change_observer.start([](const filesys::path& path)
        {
            std::cout << "[!!!] File has been modified: " << path.string() << "\n";
#ifdef _WIN32
            MessageBeep(MB_ICONWARNING);
#endif // _WIN32
        });
    }
    catch (const prog_opts::error& err)
    {
        std::cerr << "Error: " << err.what() << "\n";
        std::cout << opts_descr;
        return 1;
    }

    return 0;
}
